#ifndef _VL_MESSAGE_QUEUE__H_
#define _VL_MESSAGE_QUEUE__H_

#include <deque>
#include <memory>
#include <functional>
#include <condition_variable>
#include <mutex>
#include <thread>
#include <unordered_map>

#include "vl_timer.h"

namespace VL {


/**
 * @Author: CimZzz
 * @Date: 2022-07-15 11:56:19
 * 
 * 管道数据
 */
class VLMessageQueueData {
public:
	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 11:57:11
	 * 
	 * 构造方法
	 * 
	 * @param dataPtr 数据指针
	 * @param dataLength 数据长度
	 * @param typeCode 类型码
	 * @param syncCode 同步码
	 */
	VLMessageQueueData(std::shared_ptr<void> dataPtr = std::shared_ptr<void>(nullptr), unsigned int dataLength = 0, unsigned int typeCode = 0, unsigned int syncCode = 0);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 11:57:33
	 * 
	 * 模板实例化方法
	 * 
	 * @param dataPtr 数据指针
	 * @param typeCode 类型码
	 * @param syncCode 同步码
	 * 
	 * @return 消息数据指针
	 */
	template<typename T>
	static std::shared_ptr<VLMessageQueueData> newData(T* dataPtr, unsigned int typeCode = 0, unsigned int syncCode = 0) {
		return std::shared_ptr<VLMessageQueueData>(new VLMessageQueueData(std::shared_ptr<void>(dataPtr), sizeof(T), typeCode, syncCode));
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 11:57:33
	 * 
	 * 模板实例化方法
	 * 
	 * @param dataPtr 数据指针
	 * @param typeCode 类型码
	 * @param syncCode 类型码
	 * 
	 * @return 消息数据指针
	 */
	template<typename T>
	static std::shared_ptr<VLMessageQueueData> newData(std::shared_ptr<T> dataPtr, unsigned int typeCode = 0, unsigned int syncCode = 0) {
		return std::shared_ptr<VLMessageQueueData>(new VLMessageQueueData(std::shared_ptr<void>(dataPtr), sizeof(T), typeCode, syncCode));
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-09-13 15:05:24
	 * 
	 * 模板实例化方法
	 * 
	 * @param typeCode 类型码
	 * @param syncCode 类型码
	 * 
	 * @return 消息数据指针
	 */
	static std::shared_ptr<VLMessageQueueData> newData(unsigned int typeCode = 0, unsigned int syncCode = 0) {
		return std::shared_ptr<VLMessageQueueData>(new VLMessageQueueData(std::shared_ptr<void>(nullptr), 0, typeCode, syncCode));
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 16:53:12
	 * 
	 * 判断当前数据是否为空
	 * @return 如果为空返回 ture
	 */
	bool isEmpty();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-14 18:51:20
	 * 
	 * 获取数据指针
	 * 
	 * @return 数据指针
	 */
	std::shared_ptr<void> getData() const;


	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 16:41:06
	 * 
	 * 获取数据长度
	 * 
	 * @return 数据长度
	 */
	unsigned int getDataLength() const;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-25 07:58:38
	 * 
	 * 获取类型码
	 * 
	 * @return 类型码
	 */
	unsigned int getTypeCode() const;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-28 13:18:20
	 * 
	 * 获取同步码
	 * 
	 * @return 同步码
	 */
	unsigned int getSyncCode() const;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-14 19:04:14
	 * 
	 * 获取基本数据类型转换后的数据指针
	 * 
	 * @attention 这里只允许基本数据类型转化, 其余转换将会抛出异常
	 * 
	 * @return 转换后的数据指针
	 */
	template<typename T, typename E>
	inline std::shared_ptr<E> dataCast() const {
		return std::shared_ptr<E>(new E(*memoryCast<T>().get()));
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-14 19:04:14
	 * 
	 * 获取类型转换后的数据指针
	 * 
	 * @attention 需要注意的是, 指针转换使用的是 static_pointer_cast 方法, 一定要确保数据的正确性!
	 * 
	 * @return 转换后的数据指针
	 */
	template<typename T, typename E>
	inline std::shared_ptr<E> typeCast() const {
		return std::static_pointer_cast<E, T>(memoryCast<T>());
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-14 19:04:14
	 * 
	 * 获取内存转换后的数据指针
	 * 
	 * @return 转换后的数据指针
	 */
	template<typename T>
	inline std::shared_ptr<T> memoryCast() const {
		return std::static_pointer_cast<T, void>(this->dataPtr);
	}

private:
	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-14 18:49:53
	 * 
	 * 数据指针
	 */
	std::shared_ptr<void> dataPtr;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 14:36:45
	 * 
	 * 数据长度
	 */
	unsigned int dataLength;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-25 07:58:19
	 * 
	 * 类型码
	 */
	unsigned int typeCode;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-28 13:17:47
	 * 
	 * 同步码
	 */
	unsigned int syncCode;
};


/**
 * @Author: CimZzz
 * @Date: 2022-07-15 16:35:33
 * 
 * 消息队列
 * 线程安全
 */
class VLMessageQueue {
public:

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 16:36:10
	 * 
	 * 构造方法
	 */
	explicit VLMessageQueue();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 16:48:38
	 * 
	 * 析构方法
	 */
	~VLMessageQueue();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 16:50:25
	 * 
	 * 入队数据
	 * @param dataPtr 消息队列数据指针
	 */
	void enqueue(VLMessageQueueData* dataPtr);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 16:51:28
	 * 
	 * 入队数据
	 * @param dataPtr 消息队列数据指针
	 */
	void enqueue(std::shared_ptr<VLMessageQueueData> dataPtr);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 18:09:36
	 * 
	 * 模板方法, 入队数据
	 * @param dataPtr 数据引用
	 * @param typeCode 类型码
	 * @param syncCode 同步码
	 */
	template<typename T>
	void enqueue(const T& data, unsigned int typeCode = 0, unsigned int syncCode = 0) {
		this->enqueue(VLMessageQueueData::newData<T>(new T(data), typeCode, syncCode));
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 18:09:36
	 * 
	 * 模板方法, 入队数据
	 * @param dataPtr 数据指针
	 * @param typeCode 类型码
	 * @param syncCode 同步码
	 */
	template<typename T>
	void enqueue(T* dataPtr, unsigned int typeCode = 0, unsigned int syncCode = 0) {
		this->enqueue(VLMessageQueueData::newData<T>(dataPtr, typeCode, syncCode));
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 18:09:36
	 * 
	 * 模板方法, 入队数据
	 * @param dataPtr 数据指针
	 * @param typeCode 类型码
	 * @param syncCode 同步码
	 */
	template<typename T>
	void enqueue(std::shared_ptr<T> dataPtr, unsigned int typeCode = 0, unsigned int syncCode = 0) {
		this->enqueue(VLMessageQueueData::newData<T>(dataPtr, typeCode, syncCode));
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 16:50:25
	 * 
	 * 入队数据, 插入到队首
	 * @param dataPtr 消息队列数据指针
	 */
	void enqueueFirst(VLMessageQueueData* dataPtr);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 16:51:28
	 * 
	 * 入队数据, 插入到队首
	 * @param dataPtr 消息队列数据指针
	 */
	void enqueueFirst(std::shared_ptr<VLMessageQueueData> dataPtr);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 18:09:36
	 * 
	 * 模板方法, 入队数据, 插入到队首
	 * @param dataPtr 数据引用
	 * @param typeCode 类型码
	 * @param syncCode 同步码
	 */
	template<typename T>
	void enqueueFirst(const T& data, unsigned int typeCode = 0, unsigned int syncCode = 0) {
		this->enqueueFirst(VLMessageQueueData::newData<T>(new T(data), typeCode, syncCode));
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 18:09:36
	 * 
	 * 模板方法, 入队数据, 插入到队首
	 * @param dataPtr 数据指针
	 * @param typeCode 类型码
	 * @param syncCode 同步码
	 */
	template<typename T>
	void enqueueFirst(T* dataPtr, unsigned int typeCode = 0, unsigned int syncCode = 0) {
		this->enqueueFirst(VLMessageQueueData::newData<T>(dataPtr, typeCode, syncCode));
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 18:09:36
	 * 
	 * 模板方法, 入队数据, 插入到队首
	 * @param dataPtr 数据指针
	 * @param typeCode 类型码
	 * @param syncCode 同步码
	 */
	template<typename T>
	void enqueueFirst(std::shared_ptr<T> dataPtr, unsigned int typeCode = 0, unsigned int syncCode = 0) {
		this->enqueueFirst(VLMessageQueueData::newData<T>(dataPtr, typeCode, syncCode));
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 16:52:24
	 * 
	 * 出队数据
	 * @return 消息队列数据指针
	 * 
	 * @attention 该方法不会导致阻塞, 如果不存在数据则会返回空消息队列数据
	 */
	std::shared_ptr<VLMessageQueueData> dequeue();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 16:55:56
	 * 
	 * 出队数据
	 * 
	 * @param waitTime 等待时间, 单位毫秒
	 * 
	 * @return 消息队列数据指针
	 * 
	 * @attention 如果当前消息队列中无数据, 则会一直阻塞直至收到数据
	 * @attention 如果等待时间大于 0, 则会在等待超时后尝试获取, 如果不存在数据返回空消息队列数据
	 */
	std::shared_ptr<VLMessageQueueData> dequeueBlock(unsigned int waitTime = 0);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-26 12:44:20
	 * 
	 * 设置当前是否可以入队消息
	 * 
	 * @param isEnqueueable 如果为 true 表示当前可以入队消息
	 */
	void setEnqueueable(bool isEnqueueable);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-26 13:49:38
	 * 
	 * 唤醒等待的消息队列, 如果当前队列中不存在数据返回空指针
	 */
	void notifyAll();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 17:07:21
	 * 
	 * 清空消息队列数据
	 */
	void clear();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 17:09:26
	 * 
	 * 销毁消息队列, 与清空消息队列不同的是
	 * 一旦消息队列销毁, 将不会再接收新的消息数据, 并且全部阻塞将会被唤醒返回空
	 */
	void destroy();

private:
	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 16:55:21
	 * 
	 * 空消息队列数据
	 */
	static std::shared_ptr<VLMessageQueueData> EMPTY;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 17:11:04
	 * 
	 * 判断消息队列是否被销毁
	 */
	volatile bool isDestroy;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-26 12:45:19
	 * 
	 * 判断当前消息队列是否允许入队消息
	 */
	volatile bool isEnqueueable;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 16:58:49
	 * 
	 * 队列容器
	 */
	std::deque<std::shared_ptr<VLMessageQueueData>> queue;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 16:49:23
	 * 
	 * 线程锁
	 */
	std::mutex mutex;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-07-15 16:49:38
	 * 
	 * 条件变量
	 */
	std::condition_variable cond;
};


/**
 * @Author: CimZzz
 * @Date: 2022-08-25 00:49:52
 * 
 * 消息队列线程状态
 */
enum VLMessageQueueThreadStatus {
	// 初始化
	MQTS_Init,
	// 循环中
	MQTS_Looping,
	// 等待销毁
	MQTS_WaitDestroy,
	// 已销毁
	MQTS_Destroy
};

/**
 * @Author: CimZzz
 * @Date: 2022-08-25 00:47:25
 * 
 * 消息队列线程
 */
class VLMessageQueueThread {
public:
	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-25 00:54:26
	 * 
	 * 消息队列消费回调
	 */
	using VLMessageQueueLooper = std::function<void(const std::shared_ptr<VLMessageQueueData>&)>;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-25 00:48:01
	 * 
	 * 构造函数
	 */
	explicit VLMessageQueueThread();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-25 00:48:01
	 * 
	 * 构造函数
	 * 
	 * @param looper 消息队列消费回调
	 */
	explicit VLMessageQueueThread(VLMessageQueueLooper looper);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-25 00:57:22
	 * 
	 * 析构函数
	 */
	virtual ~VLMessageQueueThread();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-25 00:49:01
	 * 
	 * 开始消息队列循环
	 */
	void loop();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-27 14:14:37
	 * 
	 * 等待消息队列线程销毁
	 */
	void waitDestroy();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-25 00:49:17
	 * 
	 * 销毁消息队列线程
	 */
	void destroy();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-26 12:40:48
	 * 
	 * 直到消费完全部消息后, 销毁消息队列线程
	 */
	void destroyUntil();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-27 20:13:53
	 * 
	 * 清空消息队列中全部消息
	 */
	virtual void clear();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-09-13 11:09:01
	 * 
	 * 注册对应消息类型回调
	 * 
	 * @param typeCode 类型码
	 * @param looper 处理消息回调
	 * 
	 * @attention 只有消息队列线程初始化阶段才可以进行注册, 一旦消息队列线程销毁或者已开始循环, 那么将无法进行回调注册
	 */
	void registerTypeCallback(unsigned int typeCode, VLMessageQueueLooper looper);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-09-13 14:56:12
	 * 
	 * 注册对应消息类型回调, 不处理消息内容
	 * 
	 * @param typeCode 类型码
	 * @param callback 处理消息回调
	 * 
	 * @attention 只有消息队列线程初始化阶段才可以进行注册, 一旦消息队列线程销毁或者已开始循环, 那么将无法进行回调注册
	 */
	void registerTypeCallback(unsigned int typeCode, std::function<void()> callback);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-09-13 11:30:20
	 * 
	 * 注册对应消息类型回调, 并指明数据类型, 在获取消息时自动转换为对应的数据类型
	 * 
	 * @param typeCode 类型码
	 * @param looper 处理消息回调
	 * 
	 * @attention 只有消息队列线程初始化阶段才可以进行注册, 一旦消息队列线程销毁或者已开始循环, 那么将无法进行回调注册
	 */
	template<typename T>
	void registerTypeCallback(unsigned int typeCode, std::function<void(const std::shared_ptr<T>&)> callback) {
		this->registerTypeCallback(typeCode, [callback](const std::shared_ptr<VLMessageQueueData>& dataPtr) {
			callback(dataPtr->memoryCast<T>());
		});
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-09-13 11:30:20
	 * 
	 * 注册对应消息类型回调, 并指明数据类型, 在获取消息时自动转换为对应的数据类型
	 * 
	 * @param typeCode 类型码
	 * @param looper 处理消息回调
	 * 
	 * @attention 只有消息队列线程初始化阶段才可以进行注册, 一旦消息队列线程销毁或者已开始循环, 那么将无法进行回调注册
	 */
	template<typename T>
	void registerTypeCallback(unsigned int typeCode, std::function<void(const T&)> callback) {
		this->registerTypeCallback(typeCode, [callback](const std::shared_ptr<VLMessageQueueData>& dataPtr) {
			callback(*dataPtr->memoryCast<T>());
		});
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-09-13 11:30:20
	 * 
	 * 注册对应消息类型回调, 并指明数据类型, 在获取消息时自动转换为对应的数据类型
	 * 
	 * @param typeCode 类型码
	 * @param looper 处理消息回调
	 * 
	 * @attention 只有消息队列线程初始化阶段才可以进行注册, 一旦消息队列线程销毁或者已开始循环, 那么将无法进行回调注册
	 */
	template<typename T>
	void registerTypeCallback(unsigned int typeCode, std::function<void(const T*)> callback) {
		this->registerTypeCallback(typeCode, [callback](const std::shared_ptr<VLMessageQueueData>& dataPtr) {
			callback(dataPtr->memoryCast<T>().get());
		});
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-09-15 17:04:15
	 * 
	 * 注册对应消息类型同步回调
	 * 
	 * @param typeCode 类型码
	 * @param callback 处理消息回调
	 * 
	 *  @attention 只有消息队列线程初始化阶段才可以进行注册, 一旦消息队列线程销毁或者已开始循环, 那么将无法进行回调注册
	 */
	void registerTypeSyncCallback(unsigned int typeCode, std::function<void(const std::shared_ptr<VLMessageQueueData>&, unsigned int syncCode)> callback);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-09-15 17:04:15
	 * 
	 * 注册对应消息类型同步回调, 不处理消息内容
	 * 
	 * @param typeCode 类型码
	 * @param callback 处理消息回调
	 * 
	 * @attention 只有消息队列线程初始化阶段才可以进行注册, 一旦消息队列线程销毁或者已开始循环, 那么将无法进行回调注册
	 */
	void registerTypeSyncCallback(unsigned int typeCode, std::function<void(unsigned int syncCode)> callback);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-09-15 17:18:25
	 * 
	 * 注册对应消息类型同步回调, 并指明数据类型, 在获取消息时自动转换为对应的数据类型
	 * 
	 * @param typeCode 类型码
	 * @param callback 处理消息回调
	 * 
	 * @attention 只有消息队列线程初始化阶段才可以进行注册, 一旦消息队列线程销毁或者已开始循环, 那么将无法进行回调注册
	 */
	template<typename T>
	void registerTypeSyncCallback(unsigned int typeCode, std::function<void(const std::shared_ptr<T>&, unsigned int)> callback) {
		this->registerTypeCallback(typeCode, [callback](const std::shared_ptr<VLMessageQueueData>& dataPtr) {
			callback(dataPtr->memoryCast<T>(), dataPtr->getSyncCode());
		});
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-09-15 17:18:25
	 * 
	 * 注册对应消息类型同步回调, 并指明数据类型, 在获取消息时自动转换为对应的数据类型
	 * 
	 * @param typeCode 类型码
	 * @param callback 处理消息回调
	 * 
	 * @attention 只有消息队列线程初始化阶段才可以进行注册, 一旦消息队列线程销毁或者已开始循环, 那么将无法进行回调注册
	 */
	template<typename T>
	void registerTypeSyncCallback(unsigned int typeCode, std::function<void(const T&, unsigned int)> callback) {
		this->registerTypeCallback(typeCode, [callback](const std::shared_ptr<VLMessageQueueData>& dataPtr) {
			callback(*(dataPtr->memoryCast<T>()), dataPtr->getSyncCode());
		});
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-09-15 17:18:25
	 * 
	 * 注册对应消息类型同步回调, 并指明数据类型, 在获取消息时自动转换为对应的数据类型
	 * 
	 * @param typeCode 类型码
	 * @param callback 处理消息回调
	 * 
	 * @attention 只有消息队列线程初始化阶段才可以进行注册, 一旦消息队列线程销毁或者已开始循环, 那么将无法进行回调注册
	 */
	template<typename T>
	void registerTypeSyncCallback(unsigned int typeCode, std::function<void(T*, unsigned int)> callback) {
		this->registerTypeCallback(typeCode, [callback](const std::shared_ptr<VLMessageQueueData>& dataPtr) {
			callback(dataPtr->memoryCast<T>().get(), dataPtr->getSyncCode());
		});
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-27 19:13:08
	 * 
	 * 入队数据
	 * @param dataPtr 消息队列数据指针
	 */
	void enqueue(VLMessageQueueData* dataPtr);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-27 19:13:08
	 * 
	 * 入队数据
	 * @param dataPtr 消息队列数据指针
	 */
	void enqueue(std::shared_ptr<VLMessageQueueData> dataPtr);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-27 19:13:08
	 * 
	 * 模板方法, 入队数据
	 * @param dataPtr 数据引用
	 * @param typeCode 类型码
	 * @param syncCode 同步码
	 */
	template<typename T>
	void enqueue(const T& data, unsigned int typeCode = 0, unsigned int syncCode = 0) {
		this->messageQueue.enqueue(VLMessageQueueData::newData<T>(new T(data), typeCode, syncCode));
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-27 19:13:08
	 * 
	 * 模板方法, 入队数据
	 * @param dataPtr 数据指针
	 * @param typeCode 类型码
	 * @param syncCode 同步码
	 */
	template<typename T>
	void enqueue(T* dataPtr, unsigned int typeCode = 0, unsigned int syncCode = 0) {
		this->messageQueue.enqueue(VLMessageQueueData::newData<T>(dataPtr, typeCode, syncCode));
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-27 19:13:08
	 * 
	 * 模板方法, 入队数据
	 * @param dataPtr 数据指针
	 * @param typeCode 类型码
	 * @param syncCode 同步码
	 */
	template<typename T>
	void enqueue(std::shared_ptr<T> dataPtr, unsigned int typeCode = 0, unsigned int syncCode = 0) {
		this->messageQueue.enqueue(VLMessageQueueData::newData<T>(dataPtr, typeCode, syncCode));
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-27 19:13:08
	 * 
	 * 入队数据, 插入到队首
	 * @param dataPtr 消息队列数据指针
	 */
	void enqueueFirst(VLMessageQueueData* dataPtr);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-27 19:13:08
	 * 
	 * 入队数据, 插入到队首
	 * @param dataPtr 消息队列数据指针
	 */
	void enqueueFirst(std::shared_ptr<VLMessageQueueData> dataPtr);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-27 19:13:08
	 * 
	 * 模板方法, 入队数据, 插入到队首
	 * @param dataPtr 数据引用
	 * @param typeCode 类型码
	 * @param syncCode 同步码
	 */
	template<typename T>
	void enqueueFirst(const T& data, unsigned int typeCode = 0, unsigned int syncCode = 0) {
		this->messageQueue.enqueueFirst(VLMessageQueueData::newData<T>(new T(data), typeCode, syncCode));
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-27 19:13:08
	 * 
	 * 模板方法, 入队数据, 插入到队首
	 * @param dataPtr 数据指针
	 * @param typeCode 类型码
	 * @param syncCode 同步码
	 */
	template<typename T>
	void enqueueFirst(T* dataPtr, unsigned int typeCode = 0, unsigned int syncCode = 0) {
		this->messageQueue.enqueueFirst(VLMessageQueueData::newData<T>(dataPtr, typeCode, syncCode));
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-27 19:13:08
	 * 
	 * 模板方法, 入队数据, 插入到队首
	 * @param dataPtr 数据指针
	 * @param typeCode 类型码
	 * @param syncCode 同步码
	 */
	template<typename T>
	void enqueueFirst(std::shared_ptr<T> dataPtr, unsigned int typeCode = 0, unsigned int syncCode = 0) {
		this->messageQueue.enqueueFirst(VLMessageQueueData::newData<T>(dataPtr, typeCode, syncCode));
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-25 01:05:36
	 * 
	 * 判断当前是否正在执行循环
	 * 
	 * @return 如果是返回 true
	 */
	bool isLooping() const;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-27 19:26:51
	 * 
	 * 获取当前消息队列线程状态
	 */
	VLMessageQueueThreadStatus getMessageQueueThreadStatus() const;

protected:
	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-25 00:56:23
	 * 
	 * 消息队列启动回调
	 */
	virtual void onLoopBegin();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-25 01:07:06
	 * 
	 * 消息队列线程启动回调
	 */
	virtual void onLoopThreadBegin();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-25 00:55:08
	 * 
	 * 执行消息队列消费回调
	 * 
	 * @param dataPtr 消息数据指针
	 */
	virtual void onLoop(const std::shared_ptr<VLMessageQueueData>& dataPtr);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-27 20:22:45
	 * 
	 * 消息队列线程期望终止
	 * 由 [destroyUntil 触发]
	 */
	virtual void onLooperWannaEnd();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-25 01:07:06
	 * 
	 * 消息队列线程终止回调
	 */
	virtual void onLoopThreadEnd();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-25 00:56:41
	 * 
	 * 消息队列终止回调
	 */
	virtual void onLoopEnd();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-25 08:17:37
	 * 
	 * 调用回调
	 * 
	 * @param dataPtr 数据指针
	 */
	void callLooper(const std::shared_ptr<VLMessageQueueData>& dataPtr);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-25 00:52:26
	 * 
	 * 消息队列线程锁
	 */
	std::mutex mutex;

private:

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-25 00:50:42
	 * 
	 * 消息队列状态
	 */
	volatile VLMessageQueueThreadStatus status;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-25 00:54:47
	 * 
	 * 消息队列消费回调
	 */
	VLMessageQueueLooper looper;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-25 00:49:28
	 * 
	 * 消息队列
	 */
	VLMessageQueue messageQueue;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-27 14:16:06
	 * 
	 * 消息队列信号量
	 */
	std::condition_variable cond;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-25 00:52:14
	 * 
	 * 消息队列线程
	 */
	std::shared_ptr<std::thread> threadPtr;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-09-13 11:07:44
	 * 
	 * 消息队列类型回调
	 */
	std::shared_ptr<std::unordered_map<unsigned int, VLMessageQueueLooper>> typeCallback;
};

/**
 * @Author: CimZzz
 * @Date: 2022-08-25 08:01:02
 * 
 * 定时器消息队列实现
 */
class VLTimerQueueThread : public VLMessageQueueThread {
public:
	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-25 08:29:04
	 * 
	 * 定时触发回调
	 */
	using TimerCallback = std::function<void()>;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-25 08:22:13
	 * 
	 * 构造函数
	 * 
	 * @param period 周期时间, 单位毫秒, 不得小于 500 毫秒
	 */
	explicit VLTimerQueueThread(unsigned int period = 1000);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-25 08:22:13
	 * 
	 * 构造函数
	 * 
	 * @param looper 消息队列回调
	 * @param period 周期时间, 单位毫秒, 不得小于 500 毫秒
	 */
	explicit VLTimerQueueThread(VLMessageQueueLooper looper, unsigned int period = 1000);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-25 08:22:13
	 * 
	 * 构造函数
	 * 
	 * @param timerCallback 定时器回调
	 * @param period 周期时间, 单位毫秒, 不得小于 500 毫秒
	 */
	explicit VLTimerQueueThread(TimerCallback timerCallback, unsigned int period = 1000);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-25 08:22:13
	 * 
	 * 构造函数
	 * 
	 * @param looper 消息队列回调
	 * @param timerCallback 定时器回调
	 * @param period 周期时间, 单位毫秒, 不得小于 500 毫秒
	 */
	explicit VLTimerQueueThread(VLMessageQueueLooper looper, TimerCallback timerCallback, unsigned int period = 1000);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-27 20:13:53
	 * 
	 * 清空消息队列中全部消息
	 */
	virtual void clear();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-27 19:13:08
	 * 
	 * 延迟入队数据
	 * 
	 * @param dataPtr 消息队列数据指针
	 * @param delayTime 延迟时间, 单位毫秒
	 */
	void delay(VLMessageQueueData* dataPtr, uint32_t delayTime);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-27 19:13:08
	 * 
	 * 延迟入队数据
	 * 
	 * @param dataPtr 消息队列数据指针
	 * @param delayTime 延迟时间, 单位毫秒
	 */
	void delay(std::shared_ptr<VLMessageQueueData> dataPtr, uint32_t delayTime);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-27 19:13:08
	 * 
	 * 模板方法, 延迟入队数据
	 * 
	 * @param dataPtr 数据引用
	 * @param delayTime 延迟时间, 单位毫秒
	 * @param typeCode 类型码
	 * @param syncCode 同步码
	 */
	template<typename T>
	void delay(const T& data, uint32_t delayTime, unsigned int typeCode = 0, unsigned int syncCode = 0) {
		this->delay(VLMessageQueueData::newData<T>(new T(data), typeCode, syncCode), delayTime);
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-27 19:13:08
	 * 
	 * 模板方法, 延迟入队数据
	 * 
	 * @param dataPtr 数据指针
	 * @param delayTime 延迟时间, 单位毫秒
	 * @param typeCode 类型码
	 * @param syncCode 同步码
	 */
	template<typename T>
	void delay(T* dataPtr, uint32_t delayTime, unsigned int typeCode = 0, unsigned int syncCode = 0) {
		this->delay(VLMessageQueueData::newData<T>(dataPtr, typeCode, syncCode), delayTime);
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-27 19:13:08
	 * 
	 * 模板方法, 延迟入队数据
	 * 
	 * @param dataPtr 数据指针
	 * @param delayTime 延迟时间, 单位毫秒
	 * @param typeCode 类型码
	 * @param syncCode 同步码
	 */
	template<typename T>
	void delay(std::shared_ptr<T> dataPtr, uint32_t delayTime, unsigned int typeCode = 0, unsigned int syncCode = 0) {
		this->delay(VLMessageQueueData::newData<T>(dataPtr, typeCode, syncCode), delayTime);
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-27 19:13:08
	 * 
	 * 延迟入队数据, 插入到队首
	 * 
	 * @param dataPtr 消息队列数据指针
	 * @param delayTime 延迟时间, 单位毫秒
	 */
	void delayFirst(VLMessageQueueData* dataPtr, uint32_t delayTime);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-27 19:13:08
	 * 
	 * 延迟入队数据, 插入到队首
	 * 
	 * @param dataPtr 消息队列数据指针
	 * @param delayTime 延迟时间, 单位毫秒
	 */
	void delayFirst(std::shared_ptr<VLMessageQueueData> dataPtr, uint32_t delayTime);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-27 19:13:08
	 * 
	 * 模板方法, 延迟入队数据, 插入到队首
	 * 
	 * @param dataPtr 数据引用
	 * @param delayTime 延迟时间, 单位毫秒
	 * @param typeCode 类型码
	 * @param syncCode 同步码
	 */
	template<typename T>
	void delayFirst(const T& data, uint32_t delayTime, unsigned int typeCode = 0, unsigned int syncCode = 0) {
		this->delayFirst(VLMessageQueueData::newData<T>(new T(data), typeCode, syncCode), delayTime);
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-27 19:13:08
	 * 
	 * 模板方法, 延迟入队数据, 插入到队首
	 * 
	 * @param dataPtr 数据指针
	 * @param delayTime 延迟时间, 单位毫秒
	 * @param typeCode 类型码
	 * @param syncCode 同步码
	 */
	template<typename T>
	void delayFirst(T* dataPtr, uint32_t delayTime, unsigned int typeCode = 0, unsigned int syncCode = 0) {
		this->delayFirst(VLMessageQueueData::newData<T>(dataPtr, typeCode, syncCode), delayTime);
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-27 19:13:08
	 * 
	 * 模板方法, 延迟入队数据, 插入到队首
	 * 
	 * @param dataPtr 数据指针
	 * @param delayTime 延迟时间, 单位毫秒
	 * @param typeCode 类型码
	 * @param syncCode 同步码
	 */
	template<typename T>
	void delayFirst(std::shared_ptr<T> dataPtr, uint32_t delayTime, unsigned int typeCode = 0, unsigned int syncCode = 0) {
		this->delayFirst(VLMessageQueueData::newData<T>(dataPtr, typeCode, syncCode), delayTime);
	}

	/**
	 * @Author: CimZzz
	 * @Date: 2022-09-07 18:15:53
	 * 
	 * 立即调度一次定时回调
	 */
	void scheduleImmediately();

protected:
	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-25 00:56:23
	 * 
	 * 消息队列启动回调
	 */
	virtual void onLoopBegin();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-25 00:55:08
	 * 
	 * 执行消息队列消费回调
	 * 
	 * @param dataPtr 消息数据指针
	 */
	virtual void onLoop(const std::shared_ptr<VLMessageQueueData>& dataPtr);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-27 20:22:45
	 * 
	 * 消息队列线程期望终止
	 * 由 [destroyUntil 触发]
	 */
	virtual void onLooperWannaEnd();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-25 08:30:38
	 * 
	 * 触发定时器回调
	 */
	virtual void onTimer();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-25 00:56:41
	 * 
	 * 消息队列终止回调
	 */
	virtual void onLoopEnd();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-25 08:30:52
	 * 
	 * 调用定时器回调
	 */
	void callTimer();

private:
	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-27 19:34:11
	 * 
	 * 插入延迟消息数据
	 * 
	 * @param dataPtr 数据指针
	 * @param delayTime 延迟时间, 单位为毫秒
	 * @param isFirst 是否为队首消息
	 */
	void insertDelayMessage(const std::shared_ptr<VLMessageQueueData>& dataPtr, uint32_t delayTime, bool isFirst);

	/**
	 * @Author: CimZzz
	 * @Date: 2022-09-07 18:18:26
	 * 
	 * 处理定时器回调
	 */
	void handleTimerCallback();

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-25 08:29:53
	 * 
	 * 定时触发回调
	 */
	TimerCallback timerCallback;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-09-07 18:15:02
	 * 
	 * 定时器
	 */
	VLTimer timer;

	/**
	 * @Author: CimZzz
	 * @Date: 2022-08-27 19:25:21
	 * 
	 * 延迟消息队列
	 */
	std::shared_ptr<void> delayList;
};

}

#endif // _VL_MESSAGE_QUEUE__H_
